home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_100 / 169_01 / usq.c86 < prev    next >
Text File  |  1984-07-27  |  6KB  |  272 lines

  1. /*% cc -O -n % -o usq
  2. */
  3. char Version[] = {"usq revised 8-13-83"};                              /* 1.7 */
  4.  
  5. /*
  6.  *
  7.  *    08/13/83  C86 Version by Wayne Fruhwald
  8.  *    Converted to work with Computer Innovation's C86 c compiler under MSDOS.
  9.  *
  10.  */
  11.  
  12. #include <stdio.h>
  13. /*  #include <signal.h>  */                           /* 1.7 */
  14. /*  #include <ctype.h>     */                           /* 1.7 */
  15. #define TRUE 1
  16. #define FALSE 0
  17. #define ERROR (-1)
  18. #define PATHLEN 312    /* Number of characters allowed in pathname */
  19. #define OK 0
  20.  
  21. #define RECOGNIZE 0xFF76    /* unlikely pattern */
  22. #define DLE 0x90        /* repeat byte flag */
  23. #define SPEOF 256        /* special endfile token */
  24. #define NUMVALS 257        /* 256 data values plus SPEOF*/
  25. #define LARGE 30000
  26.  
  27. struct _sqleaf {        /* Decoding tree */
  28.     int _children[2];    /* left, right */
  29. };
  30. struct _sqleaf Dnode[NUMVALS - 1];
  31.  
  32.  
  33. int Bpos;        /* last bit position read */
  34. int Curin;        /* last byte value read */
  35. int Repct;        /* Number of times to retirn value */
  36. int Value;        /* current byte value or EOF */
  37.  
  38. int MakeLCPathname=TRUE;    /* translate pathname to lc if all caps */
  39. int Nlmode=FALSE;        /* zap cr's if true */
  40.  
  41. main(argc, argv)
  42. char *argv[];
  43. {
  44.     register char *cp;
  45.     register npats=0;
  46.     char **patts;
  47.     int n, errorstat;
  48.  
  49.     errorstat=0;
  50.     if(argc<2)
  51.         goto usage;
  52.     while (--argc) {
  53.         cp = *++argv;
  54.         if(*cp == '-') {
  55.             while( *++cp) {
  56.                 switch(*cp) {
  57.                 case 'n':
  58.                     Nlmode=TRUE; break;
  59.                 case 'u':
  60.                     MakeLCPathname=FALSE; break;
  61.                 default:
  62.                     goto usage;
  63.                 }
  64.             }
  65.         }
  66.         else if( !npats && argc>0) {
  67.             if(argv[0][0]) {
  68.                 npats=argc;
  69.                 patts=argv;
  70.             }
  71.         }
  72.     }
  73.     if(npats < 1) {
  74. usage:
  75.         fprintf(stderr,"Usage: usq [-nu] file ...\n");
  76.         fprintf(stderr,"\t-n Nlmode: remove carriage returns\n");
  77.         fprintf(stderr,"\tx-u preserve Uppercase pathnames\n");
  78.         exit(1);
  79.     }
  80.     for(n=0; n<npats; ++n)
  81.         errorstat |= squeeze(patts[n]);
  82.     exit(errorstat != 0);
  83. }
  84.  
  85. /*
  86.     The following code is primarily from typesq.c and utr.c.  Typesq
  87. is a modification of USQ by Dick Greenlaw.  Those modifications (usq
  88. to typesq) were made by Bob Mathias, I am responsible for the butchery
  89. done to make it work with cat.
  90.  
  91. */
  92.  
  93. FILE *in, *out;
  94. squeeze(fname)
  95. char *fname;
  96. {
  97.     register i, c;
  98.     register char *p;
  99.     register int numnodes;            /* size of decoding tree */
  100.     register unsigned crc;
  101.     unsigned filecrc;
  102.     char origname[PATHLEN];     /* Original file name without drive */
  103.  
  104.     init_cr(); init_huff(); crc=0;
  105.  
  106.     if((in=fopen( fname, "rb"))==NULL) {                           /* 1.7 */
  107.         fprintf(stderr, "usq: can't open %s\n", fname);
  108.         return ERROR;
  109.     }
  110.     if(portgetw(in) != RECOGNIZE) { /* Process header */
  111.         fprintf(stderr, "usq: %s is not a SQueezed file\n", fname);
  112.         return ERROR;
  113.     }
  114.     filecrc=portgetw(in);            /* checksum */
  115.     p = origname;                /* Get original file name */
  116.     do {                    /* send it to array */
  117.         *p = getc(in);
  118.     } while(*p++ != '\0');
  119.  
  120.     numnodes = portgetw(in);
  121.     if(numnodes < 0 || numnodes >= NUMVALS) {
  122.         fprintf(stderr, "usq: %s has invalid decode tree\n", fname);
  123.         fclose(in);
  124.         return ERROR;
  125.     }
  126.     /* Initialize for possible empty tree (SPEOF only) */
  127.     Dnode[0]._children[0] = -(SPEOF + 1);
  128.     Dnode[0]._children[1] = -(SPEOF + 1);
  129.  
  130.     for(i = 0; i < numnodes; ++i) { /* Get decoding tree from file */
  131.         Dnode[i]._children[0] = portgetw(in);
  132.         Dnode[i]._children[1] = portgetw(in);
  133.     }
  134.     /* Get translated output bytes and write file */
  135.     if(MakeLCPathname && !IsAnyLower(origname))
  136.         uncaps(origname);
  137.     fprintf(stderr, "usq: %s -> %s\n",fname,origname);
  138.     if((out=fopen(origname, "wb"))==NULL) {                        /* 1.7 */
  139.         fprintf("usq: can't create %s\n", origname);
  140.     }
  141.     while ((c = getcr()) != EOF) {
  142.         crc += c;
  143.         if ( c == '\r' && Nlmode)
  144.             continue;
  145.         putc(c, out);
  146.     }
  147.     fclose(in);
  148.     fflush(out);
  149.     fclose(out);
  150.     if( crc != filecrc ) {
  151.         fprintf(stderr, "usq: bad checksum in %s\n", fname);
  152.         return ERROR;
  153.     }
  154.     return OK;
  155. }
  156. /*** from utr.c - */
  157. /* initialize decoding functions */
  158.  
  159. init_cr()
  160. {
  161.     Repct = 0;
  162. }
  163.  
  164. init_huff()
  165. {
  166.     Bpos = 99;    /* force initial read */
  167. }
  168.  
  169. /* Get bytes with decoding - this decodes repetition,
  170.  * calls getuhuff to decode file stream into byte
  171.  * level code with only repetition encoding.
  172.  *
  173.  * The code is simple passing through of bytes except
  174.  * that DLE is encoded as DLE-zero and other values
  175.  * repeated more than twice are encoded as value-DLE-count.
  176.  */
  177.  
  178. int
  179. getcr()
  180. {
  181.     register c;
  182.  
  183.     if(Repct > 0) {
  184.         /* Expanding a repeated char */
  185.         --Repct;
  186.         return Value;
  187.     } else {
  188.         /* Nothing unusual */
  189.         if((c = getuhuff()) != DLE) {
  190.             /* It's not the special delimiter */
  191.             Value = c;
  192.             if(Value == EOF)
  193.                 Repct = LARGE;
  194.             return Value;
  195.         } else {
  196.             /* Special token */
  197.             if((Repct = getuhuff()) == 0)
  198.                 /* DLE, zero represents DLE */
  199.                 return DLE;
  200.             else {
  201.                 /* Begin expanding repetition */
  202.                 Repct -= 2;    /* 2nd time */
  203.                 return Value;
  204.             }
  205.         }
  206.     }
  207. }
  208. /* Decode file stream into a byte level code with only
  209.  * repetition encoding remaining.
  210.  */
  211.  
  212. int
  213. getuhuff()
  214. {
  215.     register i;
  216.     register bitval;
  217.  
  218.     /* Follow bit stream in tree to a leaf*/
  219.     i = 0;    /* Start at root of tree */
  220.     do {
  221.         if(++Bpos > 7) {
  222.             if((Curin = getc(in)) == ERROR)
  223.                 return ERROR;
  224.             Bpos = 0;
  225.             /* move a level deeper in tree */
  226.             i = Dnode[i]._children[1 & Curin];
  227.         } else
  228.             i = Dnode[i]._children[1 & (Curin >>= 1)];
  229.     } while(i >= 0);
  230.  
  231.     /* Decode fake node index to original data value */
  232.     i = -(i + 1);
  233.     /* Decode special endfile token to normal EOF */
  234.     i = (i == SPEOF) ? EOF : i;
  235.     return i;
  236. }
  237. /*
  238.  * Machine independent getw which always gets bytes in the same order
  239.  *  as the CP/M version of SQ wrote them
  240.  */
  241. portgetw(f)
  242. FILE *f;
  243. {
  244.     register c;
  245.  
  246.     c = getc(f)&0377;
  247.     return c + (getc(f)<<8);
  248. }
  249.  
  250.  
  251. /* make string s lower case */
  252. uncaps(s)
  253. register char *s;
  254. {
  255.     for( ; *s; ++s)
  256.         if(isupper(*s))
  257.             *s = tolower(*s);
  258. }
  259.  
  260.  
  261. /*
  262.  * IsAnyLower returns TRUE if string s has lower case letters.
  263.  */
  264. IsAnyLower(s)
  265. register char *s;
  266. {
  267.     for( ; *s; ++s)
  268.         if (islower(*s))
  269.             return TRUE;
  270.     return FALSE;
  271. }
  272.